﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Globalization;

using System.Numerics;

using NumDouble = MathNet.Numerics.LinearAlgebra.Double;
using NumComplex = MathNet.Numerics.LinearAlgebra.Complex;

namespace Estimador_EDAL.Estimador
{
    public class CMedElet
    {
        private List<CMedicao> m_ListMed;
        private NumDouble.DenseMatrix m_R;

        #region Construção do Objeto

        public CMedElet()
        {
            Defaults();
        }

        public CMedElet(CMedElet medElet)
        {
            Copy(medElet);
        }

        public CMedElet(List<CMedicao> listMed)
        {
            m_ListMed = listMed;
            Atualiza_R();
        }

        private void Defaults()
        {
            m_ListMed = new List<CMedicao>();
            m_R = null;
        }

        private void Copy(CMedElet medElet)
        {
            m_ListMed.Clear();
            foreach (CMedicao med in medElet.m_ListMed)
                m_ListMed.Add(new CMedicao(med));

            m_R = medElet.m_R;
        }

        public string ValidaDados(bool isReportZerado)
        {
            //falta implementar!!!!!!!!!!!!!!!!!!!!!!!
            return "";
        }

        #endregion Construção do Objeto

        #region Get's e Set's

        public ReadOnlyCollection<CMedicao> ListMed
        {
            get
            {
                return m_ListMed.AsReadOnly();
            }
        }

        public NumDouble.DenseMatrix R
        {
            get { return m_R; }
        }

        #endregion Get's e Set's

        #region Rotinas Privadas - Atualização da Matriz R

        private void Atualiza_R()
        {
            if (m_ListMed.Count == 0)
            {
                m_R = null;
                return;
            }

            m_R = new NumDouble.DenseMatrix(m_ListMed.Count, m_ListMed.Count, 0.0);
            for (int i = 0; i < m_ListMed.Count; i++)
                m_R[i, i] = m_ListMed[i].CoVar * m_ListMed[i].CoVar;
        }

        #endregion Atualização da Matriz R

        #region Rotinas Públicas - Add e Remove CMedicao

        public bool AddMedicao(CMedicao med)
        {
            bool achou = m_ListMed.Contains(med);
            if (achou)
                return false;

            m_ListMed.Add(med);
            Atualiza_R();
            return true;
        }

        public bool RemoveMedicao(CMedicao med)
        {
            bool achou = m_ListMed.Contains(med);
            if (!achou)
                return false;

            m_ListMed.Remove(med);
            Atualiza_R();
            return true;
        }

        #endregion Rotinas Públicas - Add e Remove CMedicao

        #region Rotinas Públicas - DE e PARA formato texto

        public void CarregaDeTxt(string str)
        {
            string[] str_Partes = str.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);

            foreach (string str_Med in str_Partes)
            {
                string str_Med_Tmp = str_Med.Trim();
                if (str_Med_Tmp.StartsWith("("))
                    continue;

                CMedicao med = new CMedicao();
                med.CarregaDeTxt(str_Med);
                m_ListMed.Add(med);
            }

            Atualiza_R();
        }

        public string DescarregaParaTxt(bool isReportZerado)
        {
            string ret = (isReportZerado) ? "\n\n" : "";

            ret += "Lista de Medições:\n\n";

            foreach (CMedicao med in m_ListMed)
                ret += med.DescarregaParaTxt() + "\n";

            ret += "\nR:\n\n";
            CultureInfo formatProvider = (CultureInfo)CultureInfo.InvariantCulture.Clone();
            formatProvider.TextInfo.ListSeparator = " ";
            ret += m_R.ToString("#0.000000\t", formatProvider);

            return ret;
        }

        #endregion
    }
}
